ll dp[505][10005], q[10005], temp[10005];//数据范围最大会爆int,所以要开long long int front, tail;//队头,队尾 structsta { int x, f, c; booloperator < (const sta a) const { return x < a.x; } } shop[505];//存的每一个商店
intmain() { int k, e, n; scanf("%d%d%d", &k, &e, &n); for (int i = 1; i <= n; i++) scanf("%d%d%d", &shop[i].x, &shop[i].f, &shop[i].c); sort(shop + 1, shop + 1 + n);//按坐标位置排序 memset(dp, 0x3f, sizeof(dp)); dp[0][0] = 0;//初始状态 for (int i = 1; i <= n; i++) { front = 0, tail = -1; for (int j = 0; j <= k; j++) temp[j] = dp[i][j] = dp[i - 1][j] + j * j * (shop[i].x - shop[i - 1].x);//注意到这里为什么需要重新开个数组,因为每次的$dp_{i,j}$是由之前更新来的,所以如果这次更新了就会影响后面的状态,所以就需要重新开个数组存一下,避免重复更新 for (int j = 0; j <= k; j++) { if (front <= tail && q[front] + shop[i].f < j) front++; while(front <= tail && temp[q[tail]] - q[tail] * shop[i].c > temp[j] - j * shop[i].c) tail--; q[++tail] = j; if (front <= tail) dp[i][j] = min(dp[i][j], temp[q[front]] + (j - q[front]) * shop[i].c); }//单调队列优化 } printf("%lld", dp[n][k] + k * k * (e - shop[n].x)); return0; }